﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OrmSmackdown;
using System.Data.SqlClient;
using System.Data;
using Microsoft.SqlServer.Management.Trace;
using Microsoft.SqlServer.Management.Common;

namespace OrmSmackdown
{
    /// <summary>
    /// Summary description for Runner
    /// </summary>
    public class Exercises
    {
        private SQLProfiling _sqlProfiler;

        private IExerciser _exerciser;
        private ILogger _logger;
        public Exercises(IExerciser excerciser, ILogger logger)
        {
            _logger = logger;
            _exerciser = excerciser;
            _sqlProfiler = new SQLProfiling();
            _sqlProfiler.TraceEvent += new EventHandler<TraceEventArgs>(_sqlProfiler_TraceEvent);
        }

        void _sqlProfiler_TraceEvent(object sender, TraceEventArgs e)
        {
            _logger.WriteLine(e.Message);
            _logger.WriteLine("======================");
            _logger.WriteLine(string.Empty);
        }

        private void GetPortalAdminEmails()
        {
            _logger.Start("GetPortalAdminEmails"); 
            var emails = _exerciser.GetPortalAdminEmails();
            //Not that great of a check but this is pretty simple.            
            foreach (var email in emails)
                _logger.WriteLine(email);

            Assert.AreEqual(Constants.NumberOfPortals, emails.Count);

            _logger.End();
        }

        private void GetUserEmails() 
        {
            _logger.Start("GetUserEmails"); 

            var emails = _exerciser.GetUserEmails();
            //Not that great of a check but this is pretty simple.
            Assert.AreEqual(Constants.NumberOfUsers, emails.Count);
            foreach(var email in emails)
                _logger.WriteLine(email);

            _logger.End();
        }

        private void GetContactEmails()
        {
            _logger.Start("GetContactEmails"); 

            var emails = _exerciser.GetContactEmails();
            //Not that great of a check but this is pretty simple.
            Assert.AreEqual(Constants.NumberOfContacts, emails.Count);
            foreach (var email in emails)
                _logger.WriteLine(email);

            _logger.End();
        }

        private void GetContactEmailsForCompany()
        {
            _logger.Start("GetContactEmailsForCompany"); 
            _logger.WriteLine(string.Format("Get contact emails for company: {0}", Constants.Company1));

            var emails = _exerciser.GetContactEmailsForCompany(Constants.Company1);
            foreach (var email in emails)
                _logger.WriteLine(email);

            _logger.End();
        }

        private void GetAverageUsersInPortal()
        {
            _logger.Start("GetAverageUsersInPortal"); 
            _logger.WriteLine("Get the average number of users per portal.");
            double averageUserPerPortal = _exerciser.GetAverageUsersPerPortal();
            _logger.WriteLine(string.Format("Average users per portal: {0:0.000}", averageUserPerPortal));
            Assert.AreEqual(Constants.AverageUsersPerPortal, averageUserPerPortal);
            _logger.End();
        }

        private void GetAdminForPortal()
        {
            _logger.Start("GetAdminForPortal"); 
            _logger.WriteLine(string.Format("Get Admin for Portal with name {0}", Constants.Portal1));
            string adminEmailAddress = _exerciser.GetAdminForPortal(Constants.Portal1);
            Assert.AreEqual(Constants.User1Email, adminEmailAddress);
            _logger.WriteLine(string.Format("Admin for Portal: {0}", adminEmailAddress));
            _logger.End();
        }

        private void GetNumberUsers()
        {
            _logger.Start("GetNumberUsers");
            int numberOfUsers = _exerciser.GetNumberOfUsers();
            Assert.AreEqual(Constants.NumberOfUsers, numberOfUsers);
            _logger.WriteLine(string.Format("Number of Users: {0}", numberOfUsers));
            _logger.End();
        }

        private void GetNumberContacts()
        {
            _logger.Start("GetNumberContacts");
            int numberOfContacts = _exerciser.GetNumberOfContacts();
            Assert.AreEqual(Constants.NumberOfContacts, numberOfContacts);
            _logger.WriteLine(string.Format("Number of Contacts: {0}", numberOfContacts));
            _logger.End();
        }

        private void GetNumberPortals()
        {
            _logger.Start("GetNumberPortals");
            int numberOfPortals = _exerciser.GetNumberOfPortals();
            Assert.AreEqual(Constants.NumberOfPortals, numberOfPortals);
            _logger.WriteLine(string.Format("Number of Portals: {0}", numberOfPortals));
            _logger.End();
        }

        private void GetDefaultCity()
        {
            _logger.Start("GetDefaultCity");
            string defaultCity = _exerciser.GetDefaultCity(Constants.User1Email);
            _logger.WriteLine(string.Format("Default city for user {0} is {1}", Constants.User1Email, defaultCity));
            Assert.AreEqual(Constants.TownWeCareAbout, defaultCity);
            _logger.End();
        }
        
        public void StartTracing(object o)
        {
            var tracer = o as TraceServer;
            while (tracer.Read())
            {
                try
                {
                    string traceType = tracer.GetValue(0).ToString();
                    if (traceType == "RPC:Completed" || traceType == "SQL:BatchCompleted")
                    {
                        _logger.WriteLine(tracer["TextData"].ToString());
                        _logger.WriteLine("======================");
                        _logger.WriteLine(string.Empty);
                    }
                }
                catch
                {
                    //does not container text data or text data is null.
                }
            }
        }

        public void RunAll(IDbConnection conn)
        {
            Support.CleanDatabase(conn);

            //TraceServer tracer = null;

            //try
            //{
            //    string traceConfiguration = string.Format(@"{0}\..\..\..\OrmSmackdownTests\SQLTracing\Standard.tdf",AppDomain.CurrentDomain.BaseDirectory);
            //    if(!System.IO.File.Exists(traceConfiguration))
            //        traceConfiguration = string.Format(@"{0}\..\..\SQLTracing\Standard.tdf", AppDomain.CurrentDomain.BaseDirectory);

            //    if (System.IO.File.Exists(traceConfiguration))
            //    {
            //        tracer = new TraceServer();
            //        ConnectionInfoBase ci = new SqlConnectionInfo("localhost");
            //        ((SqlConnectionInfo)ci).UseIntegratedSecurity = true;

            //        tracer.InitializeAsReader(ci, traceConfiguration);
            //    }
            //    else
            //        _logger.WriteLine("Could not find SQL Server Trace Configuration File.");
            //}
            //catch(Exception exc)
            //{
            //    tracer = null;
            //    _logger.WriteLine("SQL Server Profiling tools not found.  SQL Tracing not available.");
            //    _logger.WriteLine(exc.Message);
            //}

            //_logger.WriteLine(string.Format("Starting exercises on ORM: {0}  against a {1} connection", _exerciser.GetType().Namespace, conn.GetType().Name));

            //if (tracer != null)
            //    new System.Threading.Thread(StartTracing).Start(tracer);

            _sqlProfiler.StartTracing();

            _exerciser.Insert();

            GetPortalAdminEmails();
            GetContactEmailsForCompany();
            GetNumberPortals();
            GetNumberUsers();
            GetNumberContacts();
            GetDefaultCity();
            GetAdminForPortal();
            GetAverageUsersInPortal();
            GetUserEmails();
            GetContactEmails();

            _exerciser.Dispose();

            _sqlProfiler.StopTracing();
        }
    }
}
